package it.infodea.tapestrydea.components.jcr;

import it.infodea.tapestrydea.services.jcr.FileIconFactory;
import it.infodea.tapestrydea.services.jcr.JcrWorkspaceService;
import it.infodea.tapestrydea.services.jcr.nodes.wrappers.JcrFileNode;

import java.io.IOException;
import java.io.InputStream;

import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.ValueFormatException;

import org.apache.tapestry5.Block;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.RenderSupport;
import org.apache.tapestry5.StreamResponse;
import org.apache.tapestry5.annotations.IncludeStylesheet;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.util.TextStreamResponse;
import org.slf4j.Logger;

@IncludeStylesheet("SimpleContentViewer.css")
public class SimpleContentViewer {

	private static final String PREVIEW_CONTENT_EVENT = "previewContent";

	@Property
	@Parameter(required = true)
	private JcrFileNode file;

	@Parameter(defaultPrefix = "literal")
	private String title = "Preview";

	@Parameter(defaultPrefix = "literal")
	private boolean imageDownload = false;

	@Parameter(name = "link", defaultPrefix = "block")
	private Block downLinkBlock;

	@Inject
	private Block defaultLink;

	@Inject
	private ComponentResources resources;

	@Inject
	private FileIconFactory fileIconFactory;

	@Inject
	private Logger logger;

	@Inject
	private RenderSupport renderSupport;

	@Inject
	private JcrWorkspaceService jcrWorkspaceService;

	@Inject
	private Request request;

	private String allocatedId;

	enum Mode {
		READ, LOOK, DOWNLOAD
	}

	private Mode mode = Mode.DOWNLOAD;

	@SetupRender
	void setup() throws ValueFormatException, PathNotFoundException, RepositoryException {
		allocatedId = renderSupport.allocateClientId(resources);
		configureType(file);
	}

	private String getDownloadLink(JcrFileNode file) throws RepositoryException {
		String clientURL = file.toClientURL(request);
		return clientURL;
	}

	public String getPath() throws RepositoryException {
		return file.getPath();
	}

	public String getDownloadLink() throws RepositoryException {
		return getDownloadLink(file);
	}

	public String getTitle() {
		return title;
	}

	public boolean isReadable() {
		return mode == Mode.READ;
	}

	public boolean isLookable() {
		return mode == Mode.LOOK;
	}

	public boolean isVisible() {
		return mode == Mode.LOOK || mode == Mode.READ;
	}

	public String getPreviewDivId() {
		return allocatedId + "ShowDiv";
	}

	public String getPreviewLinkId() {
		return allocatedId + "ShowLink";
	}

	public Block getLinkBlock() {
		return resources.isBound("link") ? downLinkBlock : defaultLink;
	}

	public String getFileIcon() throws RepositoryException {
		logger.debug(file.getMimeType());
		return fileIconFactory.image(file.getMimeType()).toClientURL();
	}

	@OnEvent(PREVIEW_CONTENT_EVENT)
	public StreamResponse onPreviewContent(String uuid) throws RepositoryException, IOException {
		TextStreamResponse response = null;
		JcrFileNode fileByUUID = jcrWorkspaceService.getFileByUUID(uuid);
		configureType(fileByUUID);
		if (isLookable()) {
			String resourceLink = getDownloadLink(fileByUUID);
			String formatHtml = "<img src=\"%s\" />";
			response = new TextStreamResponse(fileByUUID.getMimeType(), String.format(formatHtml, resourceLink));
		} else if (isReadable()) {
			String formatHtml = "<pre>%s</pre>";
			String dataString = getDataString(fileByUUID);
			response = new TextStreamResponse(fileByUUID.getMimeType(), String.format(formatHtml, escape(dataString)));
		}
		return response;
	}

	private void configureType(JcrFileNode file) throws ValueFormatException, PathNotFoundException, RepositoryException {
		String mimeType = file.getMimeType();
		if (mimeType.startsWith("text")) {
			mode = Mode.READ;
		} else if (mimeType.startsWith("image")) {
			mode = Mode.LOOK;
		} else {
			mode = Mode.DOWNLOAD;
		}
	}

	private String escape(String dataString) {
		dataString = dataString.replaceAll("<", "&lt;");
		dataString = dataString.replaceAll(">", "&gt;");
		return dataString;
	}

	private String getDataString(JcrFileNode file) throws ValueFormatException, PathNotFoundException, RepositoryException, IOException {

		return new String(getBytes(file.getDataStream()));
	}

	private byte[] getBytes(InputStream dataStream) throws ValueFormatException, PathNotFoundException, RepositoryException {

		byte[] bytes = new byte[0];
		try {
			bytes = new byte[dataStream.available()];
			dataStream.read(bytes);
		} catch (IOException ioe) {
		} finally {
			if (dataStream != null) {
				try {
					dataStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return bytes;
	}

	public boolean isImageDownload() {
		return imageDownload;
	}

}
